/**
 * ------------------------------------------------------------------------
 * JA T3 System Plugin for Joomla 2.5
 * ------------------------------------------------------------------------
 * Copyright (C) 2004-2011 J.O.O.M Solutions Co., Ltd. All Rights Reserved.
 * @license - GNU/GPL, http://www.gnu.org/licenses/gpl.html
 * Author: J.O.O.M Solutions Co., Ltd
 * Websites: http://www.joomlart.com - http://www.joomlancers.com
 * ------------------------------------------------------------------------
 */
var jaMegaMenuMoo = new Class({

	Implements: Options,

	options: {
		slide: 0, 				//enable slide
		duration: 300, 			//slide speed. lower for slower, bigger for faster
		fading: 0,				//Enable fading
		bgopacity: 0.9, 		//set the transparent background. 0 to disable, 0<bgopacity<1: the opacity of the background
		delayHide: 500,
		direction: 'down',
		action: 'mouseenter', 	//mouseenter or click
		hidestyle: 'normal',
		offset: 5,
		fixArrow: false
	},

	toElement: function () {
		return this.menu;
	},

	initialize: function (menu, options) {
		this.menu = $(menu);
		if (!this.menu) {
			return;
		}
		this.setOptions(options);

		//ignore delayHide if no animation
		if (!this.options.slide && !this.options.fading) {
			this.options.delayHide = 10;
		}

		this.childopen = [];
		this.imgloaded = false;
		this.loaded = false;
		this.prepare();
	},

	prepare: function () {
		//preload images
		var imgElms = this.menu.getElements('img');
		if (imgElms.length && !this.imgloaded) {
			var imgSrcs = [];
			imgElms.each(function (image) {
				imgSrcs.push(image.src)
			});

			new Asset.images(imgSrcs, {
				onComplete: function () {
					this.start();
				}.bind(this)
			});
			
			this.imgloaded = true;
			//call this start if cannot load image after sometime
			this.start.delay(3000, this);
		} else {
			this.start();
		}
	},

	start: function () {
		//init once
		if (this.loaded) {
			return;
		}
		this.loaded = true;
		this.zindex = 1000;

		//get wrapper
		var pw = this.menu;
		while (pw = pw.getParent()) {
			if (pw.hasClass('main') || pw.hasClass('wrap')) {
				this.wrapper = pw;
				break;
			}
		}

		this.items = this.menu.getElements('li.mega');
		this.items.each(function (li) {
			//link item
			var link = li.getChildren('a.mega')[0],
				child = li.getChildren('.childcontent')[0],
				level0 = li.getParent().hasClass('level0'),
				parent = this.getParent(li),
				item = {
					stimer: null,
					direction: ((level0 && this.options.direction == 'up') ? 0 : 1)
				};

			//child content
			if (child) {
				var childwrap = child.getElement('.childcontent-inner-wrap'),
					childinner = child.getElement('.childcontent-inner'),
					width = childinner.getWidth(),
					height = childinner.getHeight(),
					padding = childwrap.getStyle('padding-left').toInt() + childwrap.getStyle('padding-right').toInt(),
					overflow = false;

				child.setStyles({
					width: width + 20,
					height: height + 20
				});

				childwrap.setStyle('width', width);

				if (['auto', 'scroll'].contains(childinner.getStyle('overflow'))) {
					overflow = true;

					//fix for ie6/7
					if (Browser.ie) {
						if (Browser.version <= 7) {
							childinner.setStyle('position', 'relative');
						}

						if (Browser.version == 6) {
							childinner.setStyle('height', childinner.getStyle('max-height') || 400);
						}
					}
				}

				//show direction
				if (this.options.direction == 'up') {
					if (level0) {
						child.setStyle('top', -child.getHeight()); //ajust top position
					} else {
						child.setStyle('bottom', 0);
					}
				}
			}

			if (child && this.options.bgopacity) {
				//Make transparent background
				new Element('div', {
					'class': 'childcontent-bg',
					styles: {
						width: '100%',
						height: height,
						opacity: this.options.bgopacity,
						position: 'absolute',
						top: 0,
						left: 0,
						zIndex: 1,
						background: child.getStyle('background'),
						backgroundImage: child.getStyle('background-image'),
						backgroundRepeat: child.getStyle('background-repeat'),
						backgroundColor: child.getStyle('background-color')
					}
				}).inject(childwrap, 'top');

				child.setStyle('background', 'none');
				childwrap.setStyles({
					position: 'relative',
					zIndex: 2
				});
			}

			if (child && (this.options.slide || this.options.fading)) {

				if (child.hasClass('right')) {
					child.setStyle('right', 0);
				}

				//init Fx.Styles for childcontent
				var fx = new Fx.Morph(childwrap, {
					duration: this.options.duration,
					transition: Fx.Transitions.linear,
					onComplete: this.itemAnimDone.bind(this, item),
					link: 'cancel'
				}),
					stylesOn = {};

				if (this.options.slide) {
					if (level0) {
						stylesOn[item.direction == 1 ? 'margin-top' : 'bottom'] = 0;
					} else {
						stylesOn[window.isRTL ? 'margin-right' : 'margin-left'] = 0;
					}
				}
				if (this.options.fading) {
					stylesOn['opacity'] = 1;
				}
			}

			if (child && this.options.action == 'click') {
				li.addEvent('click', function (e) {
					e.stopPropagation();

					if (li.hasClass('group')) {
						return;
					}

					if (item.status == 'open') {
						if (this.cursorIn(li, e)) {
							this.itemHide(item);
						} else {
							this.hideOthers(li);
						}
					} else {
						this.itemShow(item);
					}
				}.bind(this));
			}

			if (this.options.action == 'mouseover' || this.options.action == 'mouseenter') {
				li.addEvent('mouseover', function (e) {
					if (li.hasClass('group')) {
						return;
					}

					e.stop();
					
					clearTimeout(item.stimer);
					clearTimeout(this.atimer);

					this.intent(item, 'open');
					this.itemShow(item);

				}.bind(this))

				.addEvent('mouseleave', function (e) {
					if (li.hasClass('group')) {
						return;
					}

					clearTimeout(item.stimer);

					this.intent(item, 'close');
					if (child) {
						item.stimer = this.itemHide.delay(this.options.delayHide, this, [item]);
					} else {
						this.itemHide(item);
					}
				}.bind(this));

				//if has childcontent, don't goto link before open childcontent - fix for touch screen
				if (link && child) {
					link.addEvent('click', function (e) {
						if (!item.clickable) {
							e.stop();
						}
					});
				}

				//stop if click on menu item - prevent raise event to container => hide all open submenu
				li.addEvent('click', function (e) {
					e.stopPropagation()
				});

				if (child) {
					child.addEvent('mouseover', function () {
						clearTimeout(item.stimer);
						clearTimeout(this.atimer);

						this.intent(item, 'open');
						this.itemShow(item);
					}.bind(this)).addEvent('mouseleave', function (e) {
						e.stop();

						this.intent(item, 'close');
						clearTimeout(item.stimer);

						if (!this.cursorIn(item.el, e)) {
							this.atimer = this.hideAlls.delay(this.options.delayHide, this);
						}
					}.bind(this))
				}
			}

			//when click on a link - close all open childcontent
			if (link && !child) {
				link.addEvent('click', function (e) {
					e.stopPropagation(); //prevent to raise event up
					this.hideOthers(null);
					//Remove current class
					this.menu.getElements('.active').removeClass('active');

					//Add current class
					var p = li;
					while (p) {
						var idata = p.retrieve('item');

						p.addClass('active');
						idata.link.addClass('active');
						p = idata.parent;
					}
				}.bind(this));
			}

			Object.append(item, {
				el: li,
				parent: parent,
				link: link,
				child: child,
				childwrap: childwrap,
				childinner: childinner,
				width: width,
				height: height,
				padding: padding,
				level0: level0,
				fx: fx,
				stylesOn: stylesOn,
				overflow: overflow,
				clickable: !(link && child)
			});

			li.store('item', item);
		}, this);

		//click on windows will close all submenus
		var container = $('ja-wrapper');
		if (!container) {
			container = document.body;
		}

		container.addEvent('click', function (e) {
			this.hideAlls();
		}.bind(this));

		this.menu.getElements('.childcontent').setStyle('display', 'none');
	},

	getParent: function (el) {
		var p = el;
		while ((p = p.getParent())) {
			if (this.items.contains(p) && !p.hasClass('group')) {
				return p;
			}

			if (!p || p == this.menu) {
				return null;
			}
		}
	},

	intent: function (item, action) {
		item.intent = action;

		while (item.parent && (item = item.parent.retrieve('item'))) {
			item.intent = action;
		}
	},

	cursorIn: function (el, event) {
		if (!el || !event) {
			return false;
		}

		var pos = el.getPosition(),
			cursor = event.page;

		return (cursor.x > pos.x && cursor.x < pos.x + el.getWidth() && cursor.y > pos.y && cursor.y < pos.y + el.getHeight());
	},

	itemOver: function (item) {
		item.el.addClass('over');

		if (item.el.hasClass('haschild')) {
			item.el.removeClass('haschild').addClass('haschild-over');
		}

		if (item.link) {
			item.link.addClass('over');
		}
	},

	itemOut: function (item) {
		item.el.removeClass('over');

		if (item.el.hasClass('haschild-over')) {
			item.el.removeClass('haschild-over').addClass('haschild');
		}

		if (item.link) {
			item.link.removeClass('over');
		}
	},

	itemShow: function (item) {
		if (item.status == 'open') {
			return; //don't need do anything
		}

		this.hideOthers(item.el);

		//Setup the class
		this.itemOver(item);

		//push to show queue
		if (item.level0) {
			this.childopen.length = 0;
		}

		if (item.child) {
			this.childopen.push(item);
		}

		item.intent = 'open';
		item.status = 'open';

		this.enableclick.delay(100, this, item);

		if (item.child) {
			//reposition the submenu
			this.positionSubmenu(item);

			if (item.fx && !item.stylesOff) {
				item.stylesOff = {};
				if (this.options.slide) {
					if (item.level0) {
						item.stylesOff[item.direction == 1 ? 'margin-top' : 'bottom'] = -item.height;
					} else {
						item.stylesOff[window.isRTL ? 'margin-right' : 'margin-left'] = (item.direction == 1 ? -item.width : item.width);
					}
				}
				if (this.options.fading) {
					item.stylesOff['opacity'] = 0;
				}
				item.fx.set(item.stylesOff);
			}

			item.child.setStyles({
				display: 'block',
				zIndex: this.zindex++
			});
		}

		if (!item.fx || !item.child) {
			return;
		}

		item.child.setStyle('overflow', 'hidden');
		if (item.overflow) {
			item.childinner.setStyle('overflow', 'hidden');
		}

		item.fx.start(item.stylesOn);
	},

	itemHide: function (item) {
		clearTimeout(item.stimer);

		item.status = 'close';
		item.intent = 'close';

		this.itemOut(item);
		this.childopen.erase(item);

		if (!item.fx && item.child) {
			item.child.setStyle('display', 'none');
		}

		if (!item.fx || !item.child || item.child.getStyle('opacity') == '0') {
			return;
		}

		item.child.setStyle('overflow', 'hidden');
		if (item.overflow) {
			item.childinner.setStyle('overflow', 'hidden');
		}

		switch (this.options.hidestyle) {
		case 'fast':
			item.fx.options.duration = 100;
			item.fx.start(item.stylesOff);
			break;
		case 'fastwhenshow':
			item.fx.start(Object.merge(item.stylesOff, {
				'opacity': 0
			}));
			break;
		case 'normal':
		default:
			item.fx.start(item.stylesOff);
			break;
		}
	},

	itemAnimDone: function (item) {
		//hide done
		if (item.status == 'close') {
			//reset duration and enable opacity if not fading
			if (this.options.hidestyle.test(/fast/)) {
				item.fx.options.duration = this.options.duration;
				if (!this.options.fading) {
					item.childwrap.setStyle('opacity', 1);
				}
			}
			//hide
			item.child.setStyle('display', 'none');
			this.disableclick.delay(100, this, item);

			var pitem = item.parent ? item.parent.retrieve('item') : null;
			if (pitem && pitem.intent == 'close') {
				this.itemHide(pitem);
			}
		}

		//show done
		if (item.status == 'open') {
			item.child.setStyle('overflow', '');
			if (item.overflow) {
				item.childinner.setStyle('overflow-y', 'auto');
			}

			item.childwrap.setStyle('opacity', 1);
			item.child.setStyle('display', 'block');
		}
	},

	hideOthers: function (el) {
		this.childopen.each(function (item) {
			if (!el || (item.el != el && !item.el.contains(el))) {
				item.intent = 'close';
			}
		});

		var last = this.childopen.getLast();
		if (last && last.intent == 'close') {
			this.itemHide(last);
		}
	},

	hideAlls: function (el) {
		this.childopen.flatten().each(function (item) {
			if (!item.fx) {
				this.itemHide(item);
			} else {
				item.intent = 'close';
			}
		}, this);

		if (this.options.slide || this.options.fading) {
			var last = this.childopen.getLast();
			if (last && last.intent == 'close') {
				this.itemHide(last);
			}
		}
	},

	enableclick: function (item) {
		if (item.link && item.child) {
			item.clickable = true;
		}
	},

	disableclick: function (item) {
		item.clickable = false;
	},

	positionSubmenu: function (item) {
		var options = this.options, offsleft, offstop, left, top, stylesOff = {},
			icoord = item.el.getCoordinates(),
			bodySize = $(document.body).getScrollSize(),
			winRect = {
				top: window.getScrollTop(),
				left: window.getScrollLeft(),
				width: window.getWidth(),
				height: window.getHeight()
			},
			wrapRect = this.wrapper ? this.wrapper.getCoordinates() : {
				top: 0,
				left: 0,
				width: winRect.width,
				height: winRect.height
			};

		winRect.top = Math.max(winRect.top, wrapRect.top);
		winRect.left = Math.max(winRect.left, wrapRect.left);
		winRect.width = Math.min(winRect.width, wrapRect.width);
		winRect.height = Math.min(winRect.height, $(document.body).getScrollHeight());
		winRect.right = winRect.left + winRect.width;
		winRect.bottom = winRect.top + winRect.height;

		if (!item.level0) {
			var pitem = item.parent.retrieve('item'),
				offsety = parseFloat(pitem.child.getFirst().getStyle('margin-top')),
				offsetx = parseFloat(pitem.child.getFirst().getStyle(window.isRTL ? 'margin-right' : 'margin-left'));

			item.direction = pitem.direction;

			window.isRTL && (offsetx = 0 - offsetx);
			icoord.top -= offsety;
			icoord.bottom -= offsety;
			icoord.left -= offsetx;
			icoord.right -= offsetx;
		}

		if (item.level0) {
			if (window.isRTL) {
				offsleft = Math.max(winRect.left, icoord.right - item.width - 20);
				left = Math.max(0, offsleft - winRect.left);
			} else {
				offsleft = Math.max(winRect.left, Math.min(winRect.right - item.width, icoord.left));
				left = Math.max(0, Math.min(winRect.right - item.width, icoord.left) - winRect.left);
			}
		} else {
			if (window.isRTL) {
				if (item.direction == 1) {
					offsleft = icoord.left - item.width - 20 + options.offset;
					left = -icoord.width - 20;

					if (offsleft < winRect.left) {
						item.direction = 0;
						offsleft = Math.min(winRect.right, Math.max(winRect.left, icoord.right + item.padding - 20 - options.offset));
						left = icoord.width - 20;
						stylesOff['margin-right'] = item.width;
					}
				} else {
					offsleft = icoord.right + item.padding - 20;
					left = icoord.width - 20;

					if (offsleft + item.width > winRect.right) {
						item.direction = 1;
						offsleft = Math.max(winRect.left, icoord.left - item.width - 20);
						left = -icoord.width - 20;
						stylesOff['margin-right'] = -item.width;
					}
				}
			} else {

				if (item.direction == 1) {
					offsleft = icoord.right - options.offset;
					left = icoord.width;

					if (offsleft + item.width > winRect.right) {
						item.direction = 0;
						offsleft = Math.max(winRect.left, icoord.left - item.width - item.padding + options.offset);
						left = -icoord.width;
						stylesOff['margin-left'] = item.width;
					}
				} else {
					offsleft = icoord.left - item.width - item.padding + options.offset;
					left = -icoord.width;

					if (offsleft < winRect.left) {
						item.direction = 1;
						offsleft = Math.max(winRect.left, Math.min(winRect.right - item.width, icoord.right - options.offset));
						left = icoord.width;
						stylesOff['margin-left'] = -item.width;
					}
				}
			}
		}

		if (options.slide && item.fx && Object.getLength(stylesOff)) {
			item.fx.set(stylesOff);
		}

		// Teline IV
		if (options.fixArrow && item.childinner) {
			item.childinner.setStyle('background-position', (icoord.left - offsleft + (icoord.width / 2 - 4.5)) + 'px top');
		}

		var oldp = item.child.getStyle('display');
		item.child.setStyle('display', 'block');
		if (item.child.getOffsetParent()) {
			left = offsleft - item.child.getOffsetParent().getCoordinates().left;
		}
		item.child.setStyles({
			'margin-left': 0,
			'left': left,
			'display': oldp
		});
	}
});